package com.twang.stock.task.old;

import com.alibaba.fastjson.JSONObject;
import com.twang.stock.Entity.ShiShiData;
import com.twang.stock.common.http.HtmlTools;
import com.twang.stock.enmu.UserBusinessTypeEnum;
import com.twang.stock.entity.StockFromTHSDto;
import com.twang.stock.entity.StockFromThs;
import com.twang.stock.entity.StockInfo;
import com.twang.stock.entity.User;
import com.twang.stock.mapper.StockFromThsMapper;
import com.twang.stock.mapper.StockInfoMapper;
import com.twang.stock.mapper.UserMapper;
import com.twang.stock.service.impl.MinutesVolRuleService;
import com.twang.stock.service.jinyan.CommonService;
import com.twang.stock.service.jinyan.HolidayService;
import com.twang.stock.email.SendmailService;
import com.twang.stock.service.jinyan.UserBusinessTypeService;
import com.twang.stock.threadPool.AsycTaskExecutorConfig;
import com.twang.stock.utils.date.DateUtils;
import com.twang.stock.utils.date.HolidayCopy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 计算分时成交量   每分钟更新一次
 */
@Slf4j
@Service
public class MinutesDataTask extends  BaseTask {
    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36";
    private static String COOKIE = "v=A-9dbpYI04Zt6Ne6Um7b5cTjfgj6lEOF3ehHqgF8i95lUAH-CWTTBu241-AS";

    @Autowired
    private CommonService commonService;

    @Resource
    private StockFromThsMapper stockFromThsMapper;
    @Resource
    private HolidayService holidayService;
    @Resource
    private StockInfoMapper stockInfoMapper;
    @Autowired
    private AsycTaskExecutorConfig asycTaskExecutorConfig;

    @Autowired
    private MinutesVolRuleService minutesVolRuleService;
    @Autowired
    private UpdateToDayVol updateToDayVol;
    @Autowired
    private SendmailService sendmailService;
    @Autowired
    private UserBusinessTypeService userBusinessTypeService;
    @Resource
    private UserMapper userMapper;

   // @Scheduled(cron = "0 0/1 * * * ?")
    public void execute() throws ParseException {
        String time = DateUtils.gettradeTime();
        if (!isWorkTradeTime()) {
            return;
        }
        //先获取数据
        Map<Long,List<ShiShiData>> userMap=new HashMap<>();
        User param = new User();
        param.setAction("warn");
        List<User> users = userMapper.select(param);
        users.forEach(u-> {
            log.info(" 执行 start time={}", time);
            List<String> ids = userBusinessTypeService.selectStockCodeInfo(u.getId(), UserBusinessTypeEnum.TYPE_STOCK_INFO.getCode());
            if (CollectionUtils.isNotEmpty(ids)) {
                List<ShiShiData> listTemp = null;
                try {
                    listTemp = HtmlTools.getGpdatas(ids);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                userMap.put(u.getId(),listTemp);
            }
        });
        //再组判断更新
        for(Long v:userMap.keySet()){
            List<ShiShiData> listTemp = userMap.get(v);
            //查询
            String times = "";
            if (time.substring(8).equals("130000")) {
                //查询上一次的分时成交，中午休盘间隔90分钟
                times = holidayService.getDateMinutes(time, 90);
            } else {
                times = holidayService.getDateMinutes(time, 1);
            }
            //
            updateSetMaxVol(listTemp, times,v);
            //判断量能
            halfDayVol(listTemp,v);
            //记录回填
            insertMinutesVol(listTemp, time);
        }
    }

    private void halfDayVol(List<ShiShiData> listTemp,Long userId){
        try {
            //判断是否发生新的最大VOL
            if (CollectionUtils.isNotEmpty(listTemp)) {
                listTemp.forEach(item -> {
                    asycTaskExecutorConfig.taskQueueExecutor().execute(() -> {
                        minutesVolRuleService.halfVolRule(item.getCode(), item.getSumvol(),userId);
                        //全天的预警
                        minutesVolRuleService.todayTotalVol(item.getCode(), item.getSumvol(),userId);
                    });
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    private Integer yestoDayInfo(String code) {
        StockInfo stockInfo = new StockInfo();
        stockInfo.setCode(code);
        stockInfo.setDate(holidayService.getDayByNum(1));
        return stockInfoMapper.selectOne(stockInfo).getVolMay1();
    }

    /**
     *
     * @param listTemp
     * @param time
     */
    private void insertMinutesVol(List<ShiShiData> listTemp,String time){
        listTemp.forEach(item -> {
            StockFromThs stockFromThs = new StockFromThs();
            stockFromThs.setCode(item.getCode());
            stockFromThs.setTradeVol(new BigDecimal(item.getSumvol()));
            stockFromThs.setTradeAmount(new BigDecimal(item.getAmount()));
            stockFromThs.setToDayHighPrice(new BigDecimal(item.getMaxprice()));
            stockFromThs.setToDayLowPrice(new BigDecimal(item.getMinprice()));
            stockFromThs.setNowPrice(new BigDecimal(item.getPrice()));
            stockFromThs.setStockName(item.getGpname());
            stockFromThs.setTime(time);
            stockFromThs.setCrateTime(new Date());
            StockFromThs param = new StockFromThs();
            param.setCode(item.getCode());
            param.setTime(time);
            if(CollectionUtils.isEmpty( stockFromThsMapper.select(param))){
                stockFromThsMapper.insert(stockFromThs);
            }
        });
    }

    /**
     *
     * @param listTemp
     * @param times
     */
    private void updateSetMaxVol(List<ShiShiData> listTemp,String times,Long userId) {
        try {
            //判断是否发生新的最大VOL
            if (CollectionUtils.isNotEmpty(listTemp)) {
                listTemp.forEach(item -> {
                    //查询上一次记录
                    StockFromThs params = new StockFromThs();
                    params.setTime(times);
                    params.setCode(item.getCode());
                    StockFromThs record = stockFromThsMapper.selectOne(params);
                    if(null==record){
                        return;//可能是开盘第一分钟没有之前的数据
                    }
                    //分時量能
                    BigDecimal minutesVol = new BigDecimal(item.getSumvol()).subtract(record.getTradeVol()).setScale(2, BigDecimal.ROUND_HALF_UP);
                    //查詢當日最大分時量能
                    StockInfo stockInfo = new StockInfo();
                    stockInfo.setDate(HolidayCopy.getRealToday());
                    stockInfo.setCode(item.getCode());
                    StockInfo stockInfoRecord = stockInfoMapper.selectOne(stockInfo);
                    //初始化当日数据
                    if (null == stockInfoRecord) {
                        ShiShiData shiData = null;
                        try {
                            shiData = HtmlTools.getGpdatas(Lists.newArrayList(stockInfo.getCode())).get(0);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        stockInfoRecord = updateToDayVol.initData(shiData);
                    }
                    //如果这时候还没有拉到数据，说明今天是没有数据的，当日还没开始
                    if (null != stockInfoRecord) {
                        if (minutesVol.compareTo(new BigDecimal(null == stockInfoRecord.getVolMay1Max() ? 0 : stockInfoRecord.getVolMay1Max())) > 0) {
                            //更新最新最大量能
                            stockInfoRecord.setVolMay1Max(minutesVol.intValue());
                            stockInfoMapper.updateByPrimaryKey(stockInfoRecord);
                            //預警
                            {
                                //异步通知，不阻塞调度
                                StockInfo finalStockInfoRecord = stockInfoRecord;
                                BigDecimal finalMinutesVol = minutesVol;
                                asycTaskExecutorConfig.taskQueueExecutor().execute(() ->
                                        sendmailService.sendMailWithEmail(
                                                "【分时异动】" + finalStockInfoRecord.getName() + "   瞬时成交量：" + finalMinutesVol +
                                                        "手，请及时注意!",
                                                finalStockInfoRecord.getName(),
                                                finalStockInfoRecord.getCode(),userId));
                            }
                        } else if (minutesVol.compareTo(new BigDecimal(null == stockInfoRecord.getVolMay1Max() ? 0 : stockInfoRecord.getVolMay1Max())) == 0) {
                            //更新最新最大量能
                            stockInfoRecord.setVolMay1Max(minutesVol.intValue());
                            stockInfoMapper.updateByPrimaryKey(stockInfoRecord);
                        }
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * http://d.10jqka.com.cn/v2/realhead/hs_603758/last.js
     */
    private  StockFromTHSDto getData(String code) throws Exception {
        if(StringUtils.isEmpty(code)){
            throw new Exception("代碼不能為空！");
        }
        String url=new StringBuffer("").append("http://d.10jqka.com.cn/v2/realhead/hs_").append(code).append("/last.js").toString();
        // HttpClient 超时配置
        RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD)
                .setConnectionRequestTimeout(6000).setConnectTimeout(6000).build();
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(globalConfig).build();
        String str = getHtmlStrByUrl(url, httpClient, null, USER_AGENT);
        String data = str.split("\\(")[1];
        JSONObject obj = JSONObject.parseObject(data.split("\\)")[0]);
        Object jsonObject= obj.get("items");
        StockFromTHSDto result = JSONObject.parseObject(JSONObject.toJSONString(jsonObject),StockFromTHSDto.class);
        return result;
    }

    public static String getHtmlStrByUrl(String url, CloseableHttpClient httpClient, String COOKIE, String USER_AGENT) throws Exception {
        HttpGet httpGetForFName = new HttpGet(url);
        httpGetForFName.addHeader("User-Agent", USER_AGENT);
        httpGetForFName.addHeader("Cookie", getCOOKIE());
        httpGetForFName.addHeader("Content-Type", "text/html; charset=GBK");
        httpGetForFName.addHeader("Accept-Encoding", "gzip, deflate");
        httpGetForFName.addHeader("Connection", "keep-alive");
        // 发送请求，并执行
        CloseableHttpResponse response;
        String html = "";
        try {
            response = httpClient.execute(httpGetForFName);
            // response植入cookie
            InputStream in = response.getEntity().getContent();
            html = convertStreamToString(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return html;
    }

    private static String getCOOKIE() throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("javascript");
        ClassPathResource classPathResource = new ClassPathResource("static/js/aes.min.js");
        InputStreamReader reader=   new InputStreamReader(classPathResource.getInputStream());
        engine.eval(reader);
        if (engine instanceof Invocable) {
            Invocable invoke = (Invocable) engine; // 调用merge方法，并传入两个参数
            String c = (String) invoke.invokeFunction("v");
            COOKIE = "v=" + c;
        }
        reader.close();
        return COOKIE;
    }

    public static String convertStreamToString(InputStream in) {
        StringBuilder sb = new StringBuilder();
        try {

            InputStreamReader isr = new InputStreamReader(in, "gbk");
            BufferedReader reader = new BufferedReader(isr);
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "/n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();

    }
    private Boolean isworkTime() {
        //使用Date
        Date d = new Date();
        //格式化时间串,HH:MM:SS分别是时分秒，这里只判断分钟，有mm就够了
        //需要秒的话，就mm：ss，下面就判断是否 00:00
        SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
        String timestr = sdf.format(d);
        //判断是否为需要的时间，比如整点时分钟为00
        String regex = timestr.split(":")[1];
        if (regex.equals("59")) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

}
